////////////////////////////////////////////////////////////////////////////////

#ifndef _SERVERNETWORK_H_
#define _SERVERNETWORK_H_

////////////////////////////////////////////////////////////////////////////////

#ifndef _OBSERVER_H_
#include "observer.h"
#endif

#ifndef _COMMONTYPES_H_
#include "commontypes.h"
#endif

#ifndef _NETWORKFACTORY_H_
#include "networkfactory.h"
#endif

#ifndef _MUTEX_H_
#include "mutex.h"
#endif

#include <map>

////////////////////////////////////////////////////////////////////////////////

class Server;
class Packet;
class Buffer;
class ServerStatePacket;
class Packet;

////////////////////////////////////////////////////////////////////////////////


/** Game server network manager
*
*  @author   Roman Pasechnik
*  @since    Jun 11th, 2009
*  @updated  Jan 18th, 2010
*/
class ServerNetwork : public Observer
{
////////////////////////////////////////////////////////////////////////////////

public:

////////////////////////////////////////////////////////////////////////////////


    /** Constructor */
    ServerNetwork();


////////////////////////////////////////////////////////////////////////////////


    /** Send server state to client */
    void SendServerState( int _clientID, const Packet& _packet );


    /** Send server info to client */
    void SendServerInfo( int _clientID, const Packet& _serverPacket );


    /** Deletes marked connections. */
    void DeleteObsoleteConnections();


////////////////////////////////////////////////////////////////////////////////

private:

////////////////////////////////////////////////////////////////////////////////
//// Observer interface implementation
////////////////////////////////////////////////////////////////////////////////


    /** Notify observer about event */
    virtual void OnEvent( Event _event, Observable* _observable );


////////////////////////////////////////////////////////////////////////////////


    /** Add empty connection and call Accept() on it */
    void Accept();


    /** Send packet to client */
    void SendTCP( int _clientID, const Packet& _packet );


    /** Send packet to client */
    void SendUDP( int _clientID, const Packet& _packet );


    /** Handle accept */
    void HandleAccept();


    /** Handle receive TCP from specific client */
    void HandleReceiveTCP( const IServerConnection& _client );


    /** Handle receive UDP from specific client */
    void HandleReceiveUDP( const IServerConnection& _client );


    /** Handle disconnect */
    void HandleDisconnect( const IServerConnection& _client );


    /** Marks connection for deletion. 
        This connection will be deleted later. */
    void MarkConnectionForDeletion( int _clientID );


    /** Delete connection with specified ID */
    void DeleteConnection( int _ID );


////////////////////////////////////////////////////////////////////////////////


    /** Finds connection by ID */
    IServerConnection& FindConnectionByID( int _ID );


    /** Composes client packet from buffer and processes it */
    void ProcessPacketInBuffer( int _clientID, Buffer& _buffer );


////////////////////////////////////////////////////////////////////////////////


    /** Acceptor */
    AcceptorPtr m_Acceptor;


////////////////////////////////////////////////////////////////////////////////


    /** [Utility type]: client connections by IDs */
    class ConnectionsByIDs : public std::map<int, ServerConnectionPtr>, public Mutex{};


    /** Connections with clients */
    ConnectionsByIDs m_ConnectionsByIDs;


    /** Connections marked for deletion */
    IntVec m_ConnectionsToDelete;


////////////////////////////////////////////////////////////////////////////////
};


////////////////////////////////////////////////////////////////////////////////

#endif

////////////////////////////////////////////////////////////////////////////////

